
/* Cool Caption jQuery Plugin (RC-1)
 * 
 * http://mguy.co/coolcap
 *
 * Copyright (C) 2012 Mike Guy
 *
 * http://www.opensource.org/licenses/mit-license.php
 *
 *
 * Version: RC-1
 *
 * File: cool-caption.js
 *
 * Last updated: July 31st 2012
 */                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

(function($) {
    var coolCap = function(element,options) {
        // extend settings
        var settings = $.extend({}, $.fn.coolCap.defaults, options);

        // variables
        var vars = {
            running:    false,
            image:      '',
            child:      0
        }

        // the element
        var i   = 0;
        var e   = $(element);
            e.addClass('coolCap');
            e.data('coolCap:vars', vars);

        // children
        var c = e.children();

        // loop thru childs
        c.each(function() {
            // create element
            var ele         = document.createElement(settings.create.valueOf());
            // find the search element
            var find        = $(this).find(settings.search.valueOf());

            if(!$(find).position() || $(find).position()==undefined) {
                var find = $(this).parent().find(settings.search);
            }

            // find data
            var fdata       = $(find).data();
            // the class name of the newly created element item
            var item        = e.attr('id')+'-'+settings.aclass+'-'+i;
            // css settings
            var css         = settings.css;
            // width of the element we found
            var width       = $(find).width();
            // height of the element we found
            var height      = $(find).height();


            // auto width
            if(settings.width == '') {
                settings.width = width;
            }

            // auto height
            if(settings.height == '') {
                settings.height = Math.floor(height / settings.autoHeight);
            }

            // position of the element we found
            var pos         = $(find).position();
            // left offset position
            var left        = Number(eval(pos.left + (fdata.left ? fdata.left : settings.left)));
            // top position of new element
            var top         = Number(eval(pos.top + (fdata.top ? fdata.top : settings.top)));
            // bottom position of new element
            var bottom      =  (top + height) - (fdata.height ? fdata.height : settings.height);
            // class of new element
            var ic          = '.'+item.valueOf();

            // fallbacks
            if(left < 0) left = 0;
            if(fdata.left < left) left = fdata.left;
            if(top < 0) top = 0;

            // variables
            vars.child   = i;
            vars.image   = c.find('img:first');

            // class name
            $(ele).attr('class',item+' '+settings.cclass+' '+settings.xclass);

            // set element data
            var setEffect   = fdata.effect    ? fdata.effect   : settings.effect;
            var setPosition = fdata.position  ? fdata.position : settings.position;
            var setWidth    = (fdata.width    ? fdata.width    : settings.width)+'px';
            var setHeight   = (fdata.height   ? fdata.height   : settings.height)+'px';
            var setOpacity  = fdata.opacity   ? fdata.opacity  : settings.opacity;
            var setPrefix   = fdata.prefix    ? fdata.prefix   : settings.prefix;
            var setSuffix   = fdata.suffix    ? fdata.suffix   : settings.suffix;
            var setSpeed    = fdata.speed     ? fdata.speed    : settings.speed;

            // get caption text
            if($(find).attr(settings.key) != '' && $(find).attr(settings.key) != undefined) {
                var cap = $(find).attr(settings.key);
                if(cap.substr(0,1) == '#') cap = $(cap).html();
                $(ele).html(setPrefix + cap + setSuffix);
            }

            // append element
            $(this).append($(ele));

            // hide element
            $(ic).hide();

            // new element css
            $(ic).css({
                'width'     : (settings.responsive == 1) ? '100%' : setWidth,
                'height'    : setHeight,
                'opacity'   : setOpacity
            });

            // all systems go
            vars.running = true;

            $(this).bind('onEvent', function() {
                // already running
                if($(ic).hasClass('coolCap-active')) {
                    return false;
                }

                // do work
                else {
                    // onEventLoad trigger
                    settings.onEventLoad.call(this);

                    // position
                   switch(setPosition) {
                        // bottom
                        case 'bottom':
                            $('.'+item).css({
                                'top': bottom+'px',
                                'left': left+'px'
                            });
                        break;
                        // top
                        case 'top':
                            $('.'+item).css({
                                'top': top+'px',
                                'left': left+'px'
                            });
                        break;
                    }

                    // intro effect
                    $(ic).hide();
                    switch(setEffect) {
                        // no effect
                        case 'none':
                            $(ic).show();
                        break;
                        // slide down
                        case 'slide':
                            $(ic).stop().slideDown(setSpeed);
                        break;
                        // fade in
                        case 'fade':
                            $(ic).stop().fadeIn(setSpeed);
                        break;
                        // grow out
                        case 'grow':
                            $(ic).css({
                                'display': 'block',
                                'width':   '0px',
                                'height':  '0px',
                                'opacity': 0
                            }).stop().animate({
                                'width':   (settings.responsive == 1) ? '100%' : setWidth,
                                'height':  setHeight,
                                'opacity': setOpacity
                            }, setSpeed);
                        break;
                        // animate
                        case 'anime':
                            $(ic).css({
                                'display'   : 'block',
                                'top'       : (setPosition == 'top' ? bottom : top)+'px',
                                'opacity'   : 0
                            }).stop().animate({
                                'top'       : (setPosition == 'top' ? top : bottom)+'px',
                                'opacity'   : setOpacity
                            }, setSpeed);
                        break;
                    }
                }

                // add active class
                $(ic).addClass('coolCap-active');
            });

            $(this).bind('offEvent', function() {
                if($(ic).hasClass('coolCap-active')) {
                    // offEventLoad trigger
                    settings.offEventLoad.call(this);

                    // outro effect
                    $(ic).show();
                    switch(setEffect) {
                        // no effect
                        case 'none':
                            $(ic).hide();
                        break;
                        // slide up
                        case 'slide':
                            $(ic).stop().slideUp(setSpeed);
                        break;
                        // fade out
                        case 'fade':
                            $(ic).stop().fadeOut(setSpeed);
                        break;
                        // grow in
                        case 'grow':
                            $(ic).stop().animate({
                                'width'     : '0px',
                                'height'    : '0px',
                                'opacity'   : 0
                            }, setSpeed);

                            setTimeout(function() {
                               $(ic).hide();
                            }, (100 + setSpeed));
                        break;
                        // animate
                        case 'anime':
                            $(ic).stop().animate({
                                'top'       : (setPosition == 'top' ? bottom : top)+'px',
                                'opacity'   : 0
                            }, setSpeed);

                            setTimeout(function() {
                               $(ic).hide();
                            }, (100 + setSpeed));
                        break;
                    }

                    // remove active class
                    $(ic).removeClass('coolCap-active');
                }

                else {
                    return false;
                }
            });

            // fixed over-ride
            if(settings.fixed == 1 || (settings.offEvent && settings.onEvent)) {
                settings.hover = 0;
            }

            // hover
            if(settings.hover == 1) {
                $(this).hover(function() {
                    $(this).trigger('onEvent');
                }, function() {
                    $(this).trigger('offEvent');
                });
            }

            // fixed
            if(settings.fixed == 1) {
                $(ic).show();
                $(this).trigger('onEvent');
            }

            // custom events
            if((settings.fixed == 0 && settings.hover == 0) && (settings.onEvent && settings.offEvent)) {
                $(this).bind(settings.onEvent, function() {
                    $(this).trigger('onEvent');
                });

                $(this).bind(settings.offEvent, function() {
                    $(this).trigger('offEvent');
                });
            }

            i++;
        });

        if(settings.report == 1) {
            if(!window.console) {
                console = {
                    log:function(){}
                };
            }

            console.log('Cool-Caption Object Report');
            console.log(options);
        }
   };



    // the function
    $.fn.coolCap = function(options) {
        return this.each(function(key, value) {
            var element = $(this);

            if(element.data('coolcap')) return element.data('coolcap');

            var coolcap = new coolCap(this, options);

            element.data('coolcap', coolcap);
        });
    };

    // default settings
    $.fn.coolCap.defaults = {
        effect:         'fade',                 // default effect (fade,slide,grow,anime)
        speed:          500,                    // effect transition speed
        delay:          200,                    // hover delay time (recommended)
        position:       'bottom',               // default position of element (top or bottom)
        create:         'div',                  // html element we will append
        search:         'img:first',            // the target element (usually an image)
        key:            'title',                // the attribute key
        width:          '',                     // width of the element (blank=auto)
        height:         '',                     // height of the element (blank=auto)
        autoHeight:     '5',                    // 20% of width (recommended)
        responsive:     0,                      // makes captions responsive to element
        cclass:         'coolCap-style',        // caption class name 
        aclass:         'coolCap-append-item',  // append class name
        xclass:         '',                     // extra class names
        left:           '',                     // default left offset
        top:            '',                     // default top offset 
        prefix:         '',                     // append text before caption
        suffix:         '',                     // append text after caption
        opacity:        0.75,                   // set opacity of caption element
        hover:          1,                      // sets captions on hover event only (default)
        fixed:          0,                      // sets fixed caption and disables hover functions
        onEvent:        '',                     // bind custom event to start plugin (disables hover)
        offEvent:       '',                     // bind custom event to end plugin (disables hover)
        report:         1,                      // enable developer reporting

        onEventLoad:    function(){},           // custom function triggered when onEvent triggered
        offEventLoad:   function(){}            // custom function triggered when offEvent triggered
    };

})(jQuery);